﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using MvcContrib.UI;

namespace MvcContrib.Shp.UI.Menu
{
    public class Menu : IHtmlString
    {
        private readonly IDictionary<string, object> _attributes = new Dictionary<string, object>();
        private MenuItemBuilder _menuItemBuilder;
        private readonly MenuItem _menuItem;

        public Menu(ViewContext context)
        {
            ViewContext = context;
            Settings = new MenuSettings();
            _menuItem = new MenuItem(ViewContext, Settings);
        }

        protected ViewContext ViewContext { get; private set; }

        public MenuSettings Settings { get; set; }

        public Menu Items(Action<MenuItemBuilder> menuItemBuilder)
        {
            if (_menuItemBuilder == null)
                _menuItemBuilder = new MenuItemBuilder(_menuItem, ViewContext, Settings);

            menuItemBuilder(_menuItemBuilder);

            return this;
        }

        public Menu Attributes(IDictionary<string, object> attributes)
        {
            foreach (var attribute in attributes)
            {
                _attributes.Add(attribute);
            }

            return this;
        }

        private void PrepareRootMenuContainerAttributes()
        {
            _attributes.ReplaceAttribute(Settings.RootMenuContainerId, "id");
            _attributes.MergeAttributes(Settings.RootMenuContainerClass, "class", false);
        }

        private void PrepareRootMenuItemsCssClass()
        {
            foreach (var item in _menuItem.MenuItems)
            {
                var firstItem = _menuItem.MenuItems.FirstOrDefault();
                var lastItem = _menuItem.MenuItems.LastOrDefault();
                var attributes = item.GetItemAttributes();
                string cssClass;

                attributes.MergeAttributes(Settings.RootMenuItemsClass, "class", false);

                if (item == firstItem)
                    attributes.MergeAttributes(Settings.FirstRootMenuItemClass, "class", true);

                if (item == lastItem)
                    attributes.MergeAttributes(Settings.LastRootMenuItemClass, "class", true);
            }
        }

        public override string ToString()
        {
            return ToHtmlString();
        }

        public string ToHtmlString()
        {
            var builder = new StringBuilder();

            PrepareRootMenuContainerAttributes();

            // parse attributes
            var attributes = BuildHtmlAttributes(_attributes);

            if (attributes.Length > 0)
                attributes = " " + attributes;

            builder.AppendFormat("<ul{0}>", attributes);

            PrepareRootMenuItemsCssClass();

            foreach (var menuItem in _menuItem.MenuItems)
                builder.Append(menuItem.RenderItem());

            builder.Append("</ul>");

            return builder.ToString();
        }

        /// <summary>
        /// Converts the specified attributes dictionary of key-value pairs into a string of HTML attributes. 
        /// </summary>
        /// <returns></returns>
        protected string BuildHtmlAttributes(IDictionary<string, object> attributes)
        {
            return DictionaryExtensions.ToHtmlAttributes(attributes);
        }
    }

    public static class MenuExtensions
    {
        public static Menu Attributes(this Menu menu, params Func<object, object>[] hash)
        {
            return menu.Attributes(new Hash(hash));
        }
    }
}
